summaryrefslogtreecommitdiff
path: root/src/pages/shop/promo/[slug].jsx
diff options
context:
space:
mode:
authorit-fixcomart <it@fixcomart.co.id>2024-09-04 09:54:44 +0700
committerit-fixcomart <it@fixcomart.co.id>2024-09-04 09:54:44 +0700
commitf6a398c036d2ab833ecb798fa88e641e2f801bb0 (patch)
tree7aead541e26b5166ae3d2049fc732c7030e4e9c6 /src/pages/shop/promo/[slug].jsx
parentcbdeecd2fb8770afe46a374292e6ed3e5ec48214 (diff)
parentad168bf46919b46f708625b7d2fdc56606ec9af6 (diff)
Merge branch 'update-allPromo-fetch' into backup-release
Diffstat (limited to 'src/pages/shop/promo/[slug].jsx')
-rw-r--r--src/pages/shop/promo/[slug].jsx394
1 files changed, 394 insertions, 0 deletions
diff --git a/src/pages/shop/promo/[slug].jsx b/src/pages/shop/promo/[slug].jsx
new file mode 100644
index 00000000..cfb2c841
--- /dev/null
+++ b/src/pages/shop/promo/[slug].jsx
@@ -0,0 +1,394 @@
+import dynamic from 'next/dynamic'
+import NextImage from 'next/image';
+import { useEffect, useState } from 'react'
+import { useRouter } from 'next/router'
+import Seo from '../../../core/components/Seo.jsx'
+import Promocrumb from '../../../lib/promo/components/Promocrumb.jsx'
+import LogoSpinner from '../../../core/components/elements/Spinner/LogoSpinner.jsx'
+import ProductPromoCard from '../../../../src-migrate/modules/product-promo/components/Card.tsx'
+import React from 'react'
+import DesktopView from '../../../core/components/views/DesktopView.jsx';
+import MobileView from '../../../core/components/views/MobileView.jsx';
+import 'swiper/swiper-bundle.css';
+import useDevice from '../../../core/hooks/useDevice.js'
+import ProductFilterDesktop from '../../../lib/product/components/ProductFilterDesktopPromotion.jsx';
+import ProductFilter from '../../../lib/product/components/ProductFilter.jsx';
+import { HStack, Image, Tag, TagCloseButton, TagLabel } from '@chakra-ui/react';
+import { formatCurrency } from '../../../core/utils/formatValue.js';
+import Pagination from '../../../core/components/elements/Pagination/Pagination.js';
+import whatsappUrl from '../../../core/utils/whatsappUrl.js';
+import _ from 'lodash';
+import useActive from '../../../core/hooks/useActive.js';
+import useProductSearch from '../../../lib/promo/hooks/usePromotionSearch.js';
+
+const BasicLayout = dynamic(() => import('../../../core/components/layouts/BasicLayout.jsx'))
+
+export default function PromoDetail() {
+ const router = useRouter()
+ const { slug = '', brand ='', category='', page = '1' } = router.query
+ const [currentPage, setCurrentPage] = useState(parseInt(10) || 1);
+ const [orderBy, setOrderBy] = useState(router.query?.orderBy);
+ const popup = useActive();
+ const prefixUrl = `/shop/promo/${slug}`
+ const [queryFinal, setQueryFinal] = useState({});
+ const [limit, setLimit] = useState(30);
+ const [q, setQ] = useState('*');
+ const [finalQuery, setFinalQuery] = useState({});
+ const [products, setProducts] = useState(null);
+ const [brandValues, setBrand] = useState(
+ !router.pathname.includes('brands')
+ ? router.query.brand
+ ? router.query.brand.split(',')
+ : []
+ : []
+ );
+
+ const [categoryValues, setCategory] = useState(
+ router.query?.category?.split(',') || router.query?.category?.split(',')
+ );
+
+ const [priceFrom, setPriceFrom] = useState(router.query?.priceFrom || null);
+ const [priceTo, setPriceTo] = useState(router.query?.priceTo || null);
+
+
+ useEffect(() => {
+ const newQuery = {
+ fq: `type_value_s:${slug}`,
+ page : router.query.page? router.query.page : 1,
+ brand : router.query.brand? router.query.brand : '',
+ category : router.query.category? router.query.category : '',
+ priceFrom : router.query.priceFrom? router.query.priceFrom : '',
+ priceTo : router.query.priceTo? router.query.priceTo : '',
+ limit : router.query.limit? router.query.limit : '',
+ orderBy : router.query.orderBy? router.query.orderBy : ''
+ };
+ setFinalQuery(newQuery);
+}, [router.query, prefixUrl, slug, brand, category, priceFrom, priceTo, currentPage]);
+ useEffect(() => {
+ setQueryFinal({ ...finalQuery, q, limit, orderBy });
+ }, [router.query, prefixUrl, slug, brand, category, priceFrom, priceTo, currentPage, finalQuery]);
+
+ const { productSearch } = useProductSearch({
+ query: queryFinal,
+ operation: 'OR',
+ });
+
+
+ const pageCount = Math.ceil(productSearch.data?.response.numFound / limit);
+ const productStart = productSearch.data?.responseHeader.params.start;
+ const productRows = limit;
+ const productFound = productSearch.data?.response.numFound;
+
+ useEffect(() => {
+ setProducts(productSearch.data?.response?.products);
+ }, [productSearch]);
+
+ const brands = [];
+ for (
+ let i = 0;
+ i < productSearch.data?.facet_counts?.facet_fields?.manufacture_name_s.length;
+ i += 2
+ ) {
+ const brand =
+ productSearch.data?.facet_counts?.facet_fields?.manufacture_name_s[i];
+ const qty =
+ productSearch.data?.facet_counts?.facet_fields?.manufacture_name_s[i + 1];
+ if (qty > 0) {
+ brands.push({ brand, qty });
+ }
+ }
+
+ const categories = [];
+ for (
+ let i = 0;
+ i < productSearch.data?.facet_counts?.facet_fields?.category_name.length;
+ i += 2
+ ) {
+ const name = productSearch.data?.facet_counts?.facet_fields?.category_name[i];
+ const qty =
+ productSearch.data?.facet_counts?.facet_fields?.category_name[i + 1];
+ if (qty > 0) {
+ categories.push({ name, qty });
+ }
+ }
+
+ function capitalizeFirstLetter(string) {
+ string = string.replace(/_/g, ' ');
+ return string.replace(/(^\w|\s\w)/g, function(match) {
+ return match.toUpperCase();
+ });
+ }
+
+ const handleDeleteFilter = async (source, value) => {
+ let params = {
+ q: router.query.q,
+ orderBy: '',
+ brand: brandValues.join(','),
+ category: categoryValues?.join(','),
+ priceFrom: priceFrom || '',
+ priceTo: priceTo || '',
+ };
+
+ let brands = brandValues;
+ let catagories = categoryValues;
+ switch (source) {
+ case 'brands':
+ brands = brandValues.filter((item) => item !== value);
+ params.brand = brands.join(',');
+ await setBrandValues(brands);
+ break;
+ case 'category':
+ catagories = categoryValues.filter((item) => item !== value);
+ params.category = catagories.join(',');
+ await setCategoryValues(catagories);
+ break;
+ case 'price':
+ params.priceFrom = '';
+ params.priceTo = '';
+ break;
+ case 'delete':
+ params = {
+ q: router.query.q,
+ orderBy: '',
+ brand: '',
+ category: '',
+ priceFrom: '',
+ priceTo: '',
+ };
+ break;
+ }
+
+ handleSubmitFilter(params);
+ };
+ const handleSubmitFilter = (params) => {
+ params = _.pickBy(params, _.identity);
+ params = toQuery(params);
+ router.push(`${slug}?${params}`);
+ };
+
+
+ const toQuery = (obj) => {
+ const str = Object.keys(obj)
+ .map(key => `${encodeURIComponent(key)}=${encodeURIComponent(obj[key])}`)
+ .join('&')
+ return str
+ }
+
+ const whatPromo = capitalizeFirstLetter(slug)
+ const queryWithoutSlug = _.omit(router.query, ['slug'])
+
+ return (
+ <BasicLayout>
+ <Seo
+ title={`Promo ${Array.isArray(slug) ? slug[0] : slug} Terkini`}
+ description='B2B Marketplace MRO & Industri dengan Layanan Pembayaran Tempo, Faktur Pajak, Online Quotation, Garansi Resmi & Harga Kompetitif'
+ />
+ <Promocrumb brandName={whatPromo} />
+ <MobileView>
+ <div className='p-4 pt-0'>
+ <h1 className='mb-2 font-semibold text-h-sm'>Promo {whatPromo}</h1>
+
+ <FilterChoicesComponent
+ brandValues={brandValues}
+ categoryValues={categoryValues}
+ priceFrom={priceFrom}
+ priceTo={priceTo}
+ handleDeleteFilter={handleDeleteFilter}
+ />
+ {products?.length >= 1 && (
+ <div className='flex items-center gap-x-2 mb-5 justify-between'>
+ <div>
+ <button
+ className='btn-light py-2 px-5 h-[40px]'
+ onClick={popup.activate}
+ >
+ Filter
+ </button>
+ </div>
+ </div>
+ )}
+ {productSearch.isLoading && <div className='container flex justify-center my-4'>
+ <LogoSpinner width={48} height={48} />
+ </div>}
+ {products && (
+ <>
+ <div className='grid grid-cols-1 gap-x-1 gap-y-1'>
+ {products?.map((promotion) => (
+ <div key={promotion.id} className="min-w-36 max-w-[400px] mb-[20px] sm:w-full md:w-1/2 lg:w-1/3 xl:w-1/4 ">
+ <ProductPromoCard promotion={promotion}/>
+ </div>
+ ))}
+ </div>
+ </>
+ ) }
+
+ <Pagination
+ pageCount={pageCount}
+ currentPage={parseInt(page)}
+ url={`${prefixUrl}?${toQuery(_.omit(queryWithoutSlug, ['page']))}`}
+ className='mt-6 mb-2'
+ />
+ <ProductFilter
+ active={popup.active}
+ close={popup.deactivate}
+ brands={brands || []}
+ categories={categories || []}
+ prefixUrl={router.asPath.includes('?') ? `${router.asPath}` : `${router.asPath}?`}
+ defaultBrand={null}
+ />
+ </div>
+
+ </MobileView>
+ <DesktopView>
+ <div className='container mx-auto flex mb-3 flex-col'>
+ <div className='w-full pl-6'>
+ <h1 className='text-2xl mb-2 font-semibold'>Promo {whatPromo}</h1>
+ <div className=' w-full h-full flex flex-row items-center '>
+
+ <div className='detail-filter w-1/2 flex justify-start items-center mt-4'>
+
+ <FilterChoicesComponent
+ brandValues={brandValues}
+ categoryValues={categoryValues}
+ priceFrom={priceFrom}
+ priceTo={priceTo}
+ handleDeleteFilter={handleDeleteFilter}
+ />
+ </div>
+ <div className='Filter w-1/2 flex flex-col'>
+
+ <ProductFilterDesktop
+ brands={brands || []}
+ categories={categories || []}
+ prefixUrl={'/shop/promo'}
+ // defaultBrand={null}
+ />
+ </div>
+ </div>
+ {productSearch.isLoading ? (
+ <div className='container flex justify-center my-4'>
+ <LogoSpinner width={48} height={48} />
+ </div>
+ ) : products && products.length >= 1 ? (
+ <>
+ <div className='grid grid-cols-1 gap-x-6 sm:grid-cols-1 md:grid-cols-2 lg:grid-cols-2 xl:grid-cols-3'>
+ {products?.map((promotion) => (
+ <div key={promotion.id} className="min-w-[400px] max-w-[400px] mb-[20px] sm:min-w-[350px] md:min-w-[380px] lg:min-w-[400px] xl:min-w-[400px] ">
+ <ProductPromoCard promotion={promotion}/>
+ </div>
+ ))}
+ </div>
+ </>
+ ) : (
+ <div className="text-center my-8">
+ <p>Belum ada promo pada kategori ini</p>
+ </div>
+ )}
+ <div className='flex justify-between items-center mt-6 mb-2'>
+ <div className='pt-2 pb-6 flex items-center gap-x-3'>
+ <NextImage
+ src='/images/logo-question.png'
+ alt='Logo Question Indoteknik'
+ width={60}
+ height={60}
+ />
+ <div className='text-gray_r-12/90'>
+ <span>
+ Barang yang anda cari tidak ada?{' '}
+ <a
+ href={
+ router.query?.q
+ ? whatsappUrl('productSearch', {
+ name: router.query.q,
+ })
+ : whatsappUrl()
+ }
+ className='text-danger-500'
+ >
+ Hubungi Kami
+ </a>
+ </span>
+ </div>
+ </div>
+
+
+
+ <Pagination
+ pageCount={pageCount}
+ currentPage={parseInt(page)}
+ url={`${prefixUrl}?${toQuery(_.omit(queryWithoutSlug, ['page']))}`}
+ className='mt-6 mb-2'
+ />
+ </div>
+
+ </div>
+ </div>
+ </DesktopView>
+ </BasicLayout>
+ )
+ }
+
+const FilterChoicesComponent = ({
+ brandValues,
+ categoryValues,
+ priceFrom,
+ priceTo,
+ handleDeleteFilter,
+ }) => (
+ <div className='flex items-center mb-4'>
+ <HStack spacing={2} className='flex-wrap'>
+ {brandValues?.map((value, index) => (
+ <Tag
+ size='lg'
+ key={index}
+ borderRadius='lg'
+ variant='outline'
+ colorScheme='gray'
+ >
+ <TagLabel>{value}</TagLabel>
+ <TagCloseButton onClick={() => handleDeleteFilter('brands', value)} />
+ </Tag>
+ ))}
+
+ {categoryValues?.map((value, index) => (
+ <Tag
+ size='lg'
+ key={index}
+ borderRadius='lg'
+ variant='outline'
+ colorScheme='gray'
+ >
+ <TagLabel>{value}</TagLabel>
+ <TagCloseButton
+ onClick={() => handleDeleteFilter('category', value)}
+ />
+ </Tag>
+ ))}
+ {priceFrom && priceTo && (
+ <Tag size='lg' borderRadius='lg' variant='outline' colorScheme='gray'>
+ <TagLabel>
+ {formatCurrency(priceFrom) + '-' + formatCurrency(priceTo)}
+ </TagLabel>
+ <TagCloseButton
+ onClick={() => handleDeleteFilter('price', priceFrom)}
+ />
+ </Tag>
+ )}
+ {brandValues?.length > 0 ||
+ categoryValues?.length > 0 ||
+ priceFrom ||
+ priceTo ? (
+ <span>
+ <button
+ className='btn-transparent py-2 px-5 h-[40px] text-red-700'
+ onClick={() => handleDeleteFilter('delete')}
+ >
+ Hapus Semua
+ </button>
+ </span>
+ ) : (
+ ''
+ )}
+ </HStack>
+ </div>
+);